#!/usr/bin/perl -w
# $Id: mailhops 100 2006-10-12 17:21:41Z cmauch $
#
# Description: Script to show the route of an email message
#
# Copyright (C) 2003,2004,2005,2006 Charles Mauch <cmauch@gmail.com>
#               2000, Roland Rosenfeld <roland@spinnaker.de>
#               1999, Marius Gedminas <mgedmin@takas.lt>
#
# Verbatim copying and distribution of this entire file is permitted in any
# medium without royalty provided this header is preserved.

use strict;
use POSIX qw(mktime);
use Date::Parse;

my $verbose = 0;

# Setup
my %Months = ( Jan => 1,
               Feb => 2,
               Mar => 3,
               Apr => 4,
               May => 5,
               Jun => 6,
               Jul => 7,
               Aug => 8,
               Sep => 9,
               Oct => 10,
               Nov => 11,
               Dec => 12,
             );

# Read headers
$/ = '';
my $head = <>;
$head =~ s/\n\s+/ /g;
my @headers = split( "\n", $head );

# Parse headers
my @hops;
for ( @headers ) {
  next unless /^(>?Received|Date):/;
    my $time;
    my $host;
    my $from;
    if ( /^Date:\s+(.*)/ ) {
        $host = "Date:";
        $time = $1;
        $from = "";
    } else {
        $host = "(unknown)";
        $host = $1 if /\sby\s+([a-z0-9\-_+.]+)\s/ && $1 ne "uid";
        $from = "(unknown)";
        $from = $1 if /\sfrom\s+([a-z0-9\-_+.]+(?:\s+[(].+?[)]))\s/;
        $time = "(unknown)";
        $time = $1 if /;\s+(.+)$/;
        $time =~ s/using.*//;
    } ## end else [ if ( /^Date:\s+(.*)/ )

    my $epoch = str2time( $time );

    unshift @hops, { HOST => $host, FROM => $from, TIME => $epoch };
} ## end for ( @headers )

# Print output
print "    Host                            Date received (local)   Lag       Total lag\n";
my $nr = 0;
my ( $first, $prev );
for ( @hops ) {
    my $host = $_->{ HOST };
    my $from = $_->{ FROM };
    my $time = $_->{ TIME };
    $first = $prev = $time unless defined $first;
    printf "%2d. %-31.31s", ++$nr, $host;
    do { print "\n"; next } unless defined $time;

    my $delta = $time - $prev;
    my $neg   = $delta < 0;
    $delta = abs( $delta );
    my $delta_h = int( $delta / 3600 );
    my $delta_m = int( ( $delta - $delta_h * 3600 ) / 60 );
    my $delta_s = ( $delta - $delta_h * 3600 - $delta_m * 60 );

    my ( $sec, $min, $hour, $day, $mon, $year, undef, undef, $dst ) = localtime( $time );

    printf "  %4d-%02d-%02d  %02d:%02d:%02d  %s%02d:%02d:%02d", 1900 + $year, $mon + 1, $day, $hour, $min, $sec, $neg ? '-' : ' ', $delta_h, $delta_m, $delta_s;

    $delta   = $time - $first;
    $neg     = $delta < 0;
    $delta   = abs( $delta );
    $delta_h = int( $delta / 3600 );
    $delta_m = int( ( $delta - $delta_h * 3600 ) / 60 );
    $delta_s = ( $delta - $delta_h * 3600 - $delta_m * 60 );
    printf "  %s%02d:%02d:%02d\n", $neg ? '-' : ' ', $delta_h, $delta_m, $delta_s;
    print "     from $from\n" if $verbose;
    $prev = $time;
} ## end for ( @hops )
